#pragma once

#include <cassert>
#include <cstdint>

#define MEM_SIZE (1024*64)
#define REGISTER (1024*65)
#define SP (REGISTER + 6)
#define PC (REGISTER + 7)

class Memory{
public:
	union{
	uint8_t  b[2];
	uint16_t w;
	} mem [MEM_SIZE/2];
	
	uint16_t R[8];
		
	bool Z;
	bool N;
	bool C;
	bool V;
	
	uint8_t rb(unsigned int a)
	{
		assert(a <= MEM_SIZE || (a-REGISTER < 8 && a-REGISTER >= 0));
		if(a <= MEM_SIZE)
			return mem[a/2].b[a%2];
		else
			return (uint8_t)R[a-REGISTER];
	}
	
	uint16_t rw(unsigned int a)
	{
		assert((a <= MEM_SIZE && a%2 == 0) || (a-REGISTER < 8 && a-REGISTER >= 0));
		if(a <= MEM_SIZE)
			return mem[a/2].w;
		else
			return R[a-REGISTER];
	}
	
	void wb(unsigned int a, uint8_t v)
	{
		assert(a <= MEM_SIZE || (a-REGISTER < 8 && a-REGISTER >= 0));
		if(a <= MEM_SIZE)
			mem[a/2].b[a%2] = v;
		else
			R[a-REGISTER] = (int16_t)v;
	}
	
	void ww(unsigned int a, uint16_t v)
	{
        assert((a <= MEM_SIZE && a%2 == 0) || (a-REGISTER < 8 && a-REGISTER >= 0));
		if(a <= MEM_SIZE)
			mem[a/2].w = v;
		else
			R[a-REGISTER] = v;
	}
};

extern Memory GM;
